﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Temp_20190707_AForm.Dock;

namespace Temp_20190707_AForm
{
    public class DockPanel : System.Windows.Forms.Panel
    {
        public DockPanel()
        {
            base.BackColor = Color.Transparent;
            if (!DesignMode) InitCenterGroup();
        }


        private DockTipForm form2 = null;
        private DockTabGroup m_CenterGroup;
        public DockTabGroup CenterGroup
        {
            get { return m_CenterGroup; }
        }

        public void InitCenterGroup()
        {
            this.m_CenterGroup = new DockTabGroup();
            this.m_CenterGroup.Dock = DockStyle.Fill;
            this.m_CenterGroup.Alignment = DockAlignment.Center;
            this.Controls.Add(this.m_CenterGroup);
        }


        public void ShowDLPanel()
        {
            form2 = DockTipForm.ShowDLPanel(this);
        }
        public void HideDLPanel()
        {
            try
            {
                if (form2 != null)
                {
                    form2.Close();
                    form2.Dispose();
                    form2 = null;
                }
            }
            catch (Exception) { }
        }
        public void ShowControl(Panel ctrl)
        {
            DockFloatForm.ShowControl(this, form2, ctrl);
        }
        public void DoDock(Control ctrl)
        {
            DockEventArgs arg = form2.NewDockEventArgs();
            if (arg == null) return;

            var ctrl1 = arg.Control;
            if (ctrl1 == null) return;
            //if (!(ctrl1 is DockTabGroup)) throw new Exception(string.Format("只允许布局附着到 DockTabGroup 的控件下, 不允许附着到 类型为 '{0}' 的控件下!", ctrl1.GetType().FullName));
            //MessageBox.Show(ctrl.GetType().ToString() + " > " + ctrl1.GetType().ToString());

            this.SuspendLayout();
            if (arg.Alignment == DockAlignment.Center)
            {
                MessageBox.Show("中央增加控件: \r\n" + ctrl.GetType().ToString() + " > " + ctrl1.GetType().ToString());
            }
            else
            {
                var floatForm = ctrl.FindForm() as DockFloatForm;

                var ctrl0 = new DockTabGroup();
                ctrl0.Dock = DockStyle.Fill;
                ctrl.Dock = DockStyle.Fill;
                ctrl.Parent = ctrl0;

                var parent = ctrl1.Parent;
                var splitCtrl = new DockSplitControl();
                splitCtrl.Dock = DockStyle.Fill;
                if (arg.Alignment == DockAlignment.Top || arg.Alignment == DockAlignment.Bottom)
                    splitCtrl.Orientation = Orientation.Horizontal;
                if (arg.Alignment == DockAlignment.Right || arg.Alignment == DockAlignment.Bottom)
                { var temp = ctrl0; ctrl0 = ctrl1; ctrl1 = temp; }

                ctrl0.Parent = splitCtrl.Panel1;
                ctrl1.Parent = splitCtrl.Panel2;
                splitCtrl.Parent = parent;

                if(floatForm!=null) floatForm.Dispose();
            }
            this.ResumeLayout(true);
        }




        public DockLayoutInfo GetLayoutInfo()
        {
            return GetLayoutInfo(this);
        }
        public DockLayoutInfo GetLayoutInfo(Control parent)
        {
            if (parent == null || parent.Controls.Count <= 0) return null;
            var ctrl = parent.Controls[0];
            if (ctrl == CenterGroup)
            {
                DockLayoutInfo layout = new DockLayoutInfo(DockLayoutEnum.CenterGroup, CenterGroup);
                layout.Rect = GetRect(ctrl);
                return layout;
            }
            else if (ctrl is DockSplitControl)
            {
                var spliter = (DockSplitControl)ctrl;
                DockLayoutInfo layout = new DockLayoutInfo((spliter.Orientation == Orientation.Horizontal ? DockLayoutEnum.Horizontal : DockLayoutEnum.Vertical), spliter);
                layout.Layout1 = GetLayoutInfo(spliter.Panel1);
                layout.Layout2 = GetLayoutInfo(spliter.Panel2);
                layout.Rect = GetRect(ctrl);
                return layout;
            }
            else if (ctrl is DockTabGroup)
            {
                DockLayoutInfo layout = new DockLayoutInfo(DockLayoutEnum.OtherGroup, (DockTabGroup)ctrl);
                layout.Rect = GetRect(ctrl);
                return layout;
            }

            return null;
        }
        private Rectangle GetRect(Control ctrl)
        {
            Rectangle rect1 = this.RectangleToScreen(new Rectangle(Point.Empty, this.Size));
            Rectangle rect2 = ctrl.RectangleToScreen(new Rectangle(Point.Empty, ctrl.Size));
            Rectangle rect3 = new Rectangle(rect2.X - rect1.X, rect2.Y - rect1.Y, rect2.Width, rect2.Height);
            return rect3;
        }




    }

    public class DockLayoutInfo
    {
        public DockLayoutInfo(DockLayoutEnum @enum, DockTabGroup ctrl)
        {
            this.Enum = @enum;
            this.TabGroup = ctrl;
        }
        public DockLayoutInfo(DockLayoutEnum @enum, DockSplitControl ctrl)
        {
            this.Enum = @enum;
            this.SplitControl = ctrl;
        }

        public DockLayoutEnum Enum { get; set; }
        public Rectangle Rect { get; set; }
        public DockTabGroup TabGroup { get; set; }
        public DockSplitControl SplitControl { get; set; }
        public DockLayoutInfo Layout1 { get; set; }
        public DockLayoutInfo Layout2 { get; set; }
        public DockTipGroupRect TipRect
        {
            get
            {
                Rectangle rect1 = this.Rect;
                Rectangle rect2 = new Rectangle(0,0,90, 90);
                if (rect1.Width < rect2.Width || rect1.Height < rect2.Height) return DockTipGroupRect.Empty;
                Rectangle rect3 = new Rectangle((rect1.X) + (rect1.Width - rect2.Width) / 2, (rect1.Y) + (rect1.Height - rect2.Height) / 2, rect2.Width, rect2.Height);
                return new DockTipGroupRect(rect3);
            }
        }


        public bool MouseInRect(DockPanel dockPanel)
        {
            var point1 = System.Windows.Forms.Control.MousePosition;
            var point2 = dockPanel.PointToClient(point1);
            return Rect.Contains(point2);
        }
        public DockAlignment MouseInTipRect(DockPanel dockPanel)
        {
            var point1 = System.Windows.Forms.Control.MousePosition;
            var point2 = dockPanel.PointToClient(point1);
            return TipRect.Contains(point2);
        }

        [Obsolete("作废", true)]
        public DockLayoutInfo GetContent()
        {
            if (this.Enum == DockLayoutEnum.CenterGroup) return this;

            var result1 = Layout1 == null ? null : Layout1.GetContent();
            if (result1 != null) return result1;

            var result2 = Layout2 == null ? null : Layout2.GetContent();
            if (result2 != null) return result2;

            return null;
        }
        public List<DockLayoutInfo> GetTabGroups()
        {
            if (this.Enum == DockLayoutEnum.CenterGroup) return new List<DockLayoutInfo> { this };
            if (this.Enum == DockLayoutEnum.OtherGroup) return new List<DockLayoutInfo> { this };

            List<DockLayoutInfo> list = new List<DockLayoutInfo>();

            var result1 = Layout1 == null ? null : Layout1.GetTabGroups();
            if (result1 != null) list.AddRange(result1);

            var result2 = Layout1 == null ? null : Layout2.GetTabGroups();
            if (result2 != null) list.AddRange(result2);

            return list;
        }
    }

    public struct DockTipGroupRect
    {
        public static readonly DockTipGroupRect Empty = new DockTipGroupRect();

        public DockTipGroupRect(Rectangle rect) : this()
        {
            int width = rect.Width;
            int height = rect.Height;
            RectFull = rect;
            RectCenter = new Rectangle(RectFull.X + (width / 3), RectFull.Y + (height / 3), width / 3, height / 3);
            RectTop = new Rectangle(RectFull.X + (width / 3), RectFull.Y, width / 3, height / 3);
            RectBottom = new Rectangle(RectFull.X + (width / 3), RectFull.Y + (height * 2 / 3), width / 3, height / 3);
            RectLeft = new Rectangle(RectFull.X, RectFull.Y + (height / 3), width / 3, height / 3);
            RectRight = new Rectangle(RectFull.X + (width * 2 / 3), RectFull.Y + (height / 3), width / 3, height / 3);
        }

        public Rectangle RectFull { get; set; }
        public Rectangle RectCenter { get; set; }
        public Rectangle RectTop { get; set; }
        public Rectangle RectBottom { get; set; }
        public Rectangle RectLeft { get; set; }
        public Rectangle RectRight { get; set; }

        public int Width { get { return RectFull.Width; } }
        public int Height { get { return RectFull.Height; } }

        public DockAlignment Contains(Point point)
        {
            if(RectCenter.Contains(point)) return DockAlignment.Center;
            if(RectTop.Contains(point)) return DockAlignment.Top;
            if(RectBottom.Contains(point)) return DockAlignment.Bottom;
            if(RectLeft.Contains(point)) return DockAlignment.Left;
            if(RectRight.Contains(point)) return DockAlignment.Right;
            return DockAlignment.None;
        }
    }


    public enum DockLayoutEnum
    {
        CenterGroup,
        OtherGroup,
        Vertical,
        Horizontal,
    }

    public enum DockAlignment
    {
        None,
        Top,
        Bottom,
        Left,
        Right,
        Center,
    }

    public class DockEventArgs : EventArgs
    {
        public DockTabGroup Control;
        public DockLayoutInfo TipLayout;
        public DockAlignment Alignment;
    }

}
